#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'tyh'
__mtime__ = '18-10-7'
# code is far away from bugs with the god animal protecting ~
"""
import datetime
import logging
from decimal import Decimal

from rest_framework import serializers

from address.models import Address
from goods.models import SKU, Goods
from orders.models import OrderInfo, OrderGoods
from django_redis import get_redis_connection
from django.db import transaction

class SKUSerializer(serializers.ModelSerializer):
    count = serializers.IntegerField(min_value=1)

    class Meta:
        model = SKU
        fields = ('id','name','default_image_url','price','count')


class OrderListSerializer(serializers.Serializer):

    freight = serializers.DecimalField(min_value=10, max_value=20, max_digits=10, decimal_places=2)
    skus = SKUSerializer(many=True)

    # freight	decimal	是	运费
    # skus	sku[]	是	结算的商品列表
        # id	int	是	商品id
        # name	str	是	商品名称
        # default_image_url	str	是	商品默认图片
        # price	decimal	是	商品单价
        # count

class OrderCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = OrderInfo
        fields = ('order_id','address','pay_method',)
        extra_kwargs = {'order_id': {'read_only': True, }, 'address': {'required': True, },
            'pay_method': {'required': True, }, }

    # 当数据表有外键存在时，默认是以id的形式进行验证的，不需要再额外操作，再写验证器反而会出错
    # def validate_address(self, value):
    #     try:
    #         Address.objects.get(id=value)
    #     except Exception as e:
    #         raise serializers.ValidationError('输入的地址无效')


    def create(self, validated_data):
        user = self.context['request'].user

        address = validated_data.get('address')
        address_id = address.id
        pay_method = validated_data.get('pay_method')

        order_id = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

        # 从购物车中读取商品信息
        redis_conn = get_redis_connection('cart')

        skus_count_dict = redis_conn.hgetall('cart_%s' % user.id)
        skus_select_set = redis_conn.smembers('cart_selected_%s' % user.id)

        skus_dict ={}
        for sku, count in skus_count_dict.items():
            if sku in skus_select_set:
                skus_dict[int(sku)] = int(count)


        # 新建事务操作, 改写库存并新建订单对应的商品信息
        with transaction.atomic():

            # 设置事务的初始保存点，如果事务不成功，则回滚到这个保存点
            savepoint = transaction.savepoint()
            # 生成订单信息
            order = OrderInfo.objects.create(order_id=order_id, total_count=0, total_amount=0, freight=Decimal(10.00),
                                             pay_method=pay_method, address_id=address_id, user_id=user.id)

            try:
                total_count = 0
                total_amount = 10               # 运费10块
                for sku_id in skus_dict.keys():
                    while True:
                        sku = SKU.objects.get(id=sku_id)
                        count = skus_dict.get(sku.id)

                        goods = OrderGoods.objects.create(
                            count = count,
                            price = sku.price,
                            sku_id = sku.id,
                            order_id = order_id,
                        )

                        if sku.stock < count:
                            raise Exception("库存不够")

                        sku_old_stock,sku_old_sales = sku.stock,sku.sales

                        sku_new_stock = sku_old_stock - count
                        sku_new_sales = sku_old_sales + count

                        result_sql = 0
                        result_sql += SKU.objects.filter(id=sku_id, stock=sku_old_stock).update(stock=sku_new_stock, sales=sku_new_sales)

                        goods = sku.goods
                        result_sql += Goods.objects.filter(id=goods.id, sales=goods.sales).update(sales=goods.sales+count)

                        if result_sql == 0 :
                            transaction.savepoint_rollback(savepoint)
                            continue

                        # 订单总数量和总金额
                        total_count += count
                        total_amount += sku.price * count

                        break

                order.total_amount = total_amount
                order.total_count = total_count
                order.save()

            except Exception as e:
                logger = logging.getLogger('django')
                logger.error(e)                                             #出错则回滚操作，并记录，抛出异常
                transaction.savepoint_rollback(savepoint)
                raise


            transaction.savepoint_commit(savepoint)

            # 清除redis中选中的商品
            pl = redis_conn.pipeline()
            pl.hdel('cart_%s' % user.id, *skus_dict.keys())
            pl.srem('cart_selected_%s' % user.id, *skus_dict.keys())
            pl.execute()

            return order








